<?php

userelation("atkmanytoonerelation");
userelation("atkonetomanyrelation");
useattrib("atklistattribute");
useattrib("atkdateattribute");
useattrib("atktextattribute");
useattrib("atknumberattribute");
useattrib("atkdummyattribute");
useattrib("atkboolattribute");
useattrib("atkcurrencyattribute");

class contracts extends atkNode
{
  var $m_archive;

  function contracts($name="contracts", $flags=0)
  {
    $this->atkNode($name, $flags | NF_ADD_LINK | NF_EDITAFTERADD | NF_EXPORT);

    $this->add(new atkNumberAttribute("id",AF_AUTOKEY));
    $this->add(new atkAttribute("contractnumber",AF_SEARCHABLE|AF_FORCE_LOAD, 20));
    $this->add(new atkAttribute("contractname",AF_SEARCHABLE|AF_OBLIGATORY|AF_FORCE_LOAD));
    $this->add(new atkManyToOneRelation("contracttype","organization.contracttype",AF_SEARCHABLE|AF_OBLIGATORY|AF_RELATION_AUTOLINK));
    $attr = $this->add(new atkManyToOneRelation("customer","organization.organizationselector",AF_SEARCHABLE|AF_OBLIGATORY|AF_RELATION_AUTOLINK|AF_LARGE));
    $attr->setAutoLinkDestination('organization.organization');
    $this->add(new atkListAttribute("billing_type", array("by_period","on_delivery"), array("period","delivery"),AF_LIST_NO_NULL_ITEM | AF_HIDE_LIST));
    $attr = $this->add(new atkListAttribute("billing_period",array("no_billing_period","monthly","quarterly","yearly", "per_incident"),"",AF_OBLIGATORY|AF_HIDE_LIST));
    $attr->addOnChangeHandler("check_billing_period('billing_period', 'ar_period_price', 'period_price');");
    $this->add(new atkCurrencyAttribute("period_price", AF_HIDE_LIST,13,"",2));
    $this->add(new atkDateAttribute("startdate","","", 0, 0, AF_OBLIGATORY|AF_HIDE_LIST));
    $this->add(new atkDummyAttribute("enddate_expire_warning",atktext("enddate_expire_warning","organization","contracts"),AF_HIDE_LIST));
    $this->add(new atkDateAttribute("enddate","","", 0, 0, AF_OBLIGATORY));
    $this->add(new atkDateAttribute("term_of_notice","","", 0, 0));
    $this->add(new atkListAttribute("aftercalculation", array("no","yes"), array(0,1),AF_HIDE_LIST | AF_LIST_NO_NULL_ITEM));
    $this->add(new atkCurrencyAttribute("priceperhour",AF_HIDE_LIST,10,"",2));
    $this->add(new atkDummyAttribute("status_change_warning", atktext("status_change_warning","organization","contracts"),AF_HIDE_LIST));
    $this->add(new atkListAttribute("status", array("active", "archived"), "", AF_OBLIGATORY|AF_HIDE_LIST));
    $this->add(new atkTextAttribute("description", TEXT_SMALL, AF_HIDE_LIST ));
    $this->add(new atkOneToManyRelation("projects", "organization.contract_project", "contract_id", AF_HIDE_LIST));

    $this->addAllowedAction("linkproject");
    $this->addSecurityMap("export", "admin");
    $this->setTable("contract","contract");
    $this->setOrder("contract.startdate");
  }

  /**
   * Hack! Change display of attribute projects in edit action
   *
   * Add a select link right beside the 'Add project' link. Normally it would
   * only be possible to add the new link under the 'Add project' link because of the <br />
   * that is generated by the edit function of the atkOneToManyRelation.
   *
   * @param array record a record
   * @param string prefix the prefix for the record
   * @param string mode the mode
   * @return string html output of edit-function of atkManyToOneRelation with a brand new 'select' link
   */
  function projects_edit($record, $prefix="", $mode="")
  {
  	$attr = &$this->getAttribute("projects");
  	$result = $attr->edit($record, $prefix, $mode )	;
  	$result = atk_substr($result, 0, -6);										//Remove the '<br />' from the end

  	$target_url = dispatch_url("organization.contracts", "linkproject", array("projectid"=>"[id]", "contractid"=>$record["id"]));
 	$select_url = dispatch_url("organization.contract_projectselector", "select", array("atkfilter"=>"projectid=[id]","atktarget"=>atkurlencode($target_url)));
 	$select = session_url($select_url,SESSION_NESTED);

 	//Add link to result
    return $result."&nbsp;&nbsp;&nbsp;".href($select,atktext("selectandaddnewproject","organization","contracts"))."<br />";
  }


   /**
   * Make the dropdownlist show an 'empty' option.
   *
   * Hack! Needed to make the dropdownlist show an 'empty' option, even though the field is obligatory.
   * todo: remove this when atk has a feature for this.
   *
   * @param type name description
   * @return type description
   */
  function contracttype_edit($record, $prefix="", $mode="")
  {
  	$attr = &$this->getAttribute("contracttype");

  	//Check if the behaviour change is actually needed.
  	if($attr->hasFlag(AF_OBLIGATORY))//yes needed
  	{
  	  //Make the dropdownlist show an 'empty' option, even though the field is obligatory.
  	  $attr->m_flags ^= AF_OBLIGATORY;
      $result = $attr->edit($record, $prefix, $mode);
      
      //Change back to normal behaviour
      $attr->m_flags |= AF_OBLIGATORY;
      return $result;
  	}
  	else   //not needed
      return $attr->edit($record, $prefix, $mode);
  }

  /**
   * Make the dropdownlist show an 'empty' option.
   *
   * Hack! Needed to make the dropdownlist show an 'empty' option, even though the field is obligatory.
   * todo: remove this when atk has a feature for this.
   *
   * @param type name description
   * @return type description
   */
  function customer_edit($record, $prefix="", $mode="")
  {
  	$attr = &$this->getAttribute("customer");

  	//Check if the behaviour change is actually needed.
  	if($attr->hasFlag(AF_OBLIGATORY))//yes needed
  	{
  	  //Make the dropdownlist show an 'empty' option, even though the field is obligatory.
  	  $attr->m_flags ^= AF_OBLIGATORY;
	  $result = $attr->edit($record, $prefix, $mode);

	  //Change back to normal behaviour
      $attr->m_flags |= AF_OBLIGATORY;
      return $result;
  	}
  	else   //not needed
      return $attr->edit($record, $prefix, $mode);
  }

  /**
   * Make the dropdownlist show an 'empty' option.
   *
   * Hack! Needed to make the dropdownlist show an 'empty' option, even though the field is obligatory.
   * todo: remove this when atk has a feature for this.
   *
   * @param type name description
   * @return type description
   */
  function billing_period_edit($record, $prefix="", $mode="")
  {
  	$attr = &$this->getAttribute("billing_period");

  	//Check if the behaviour change is actually needed.
  	if($attr->hasFlag(AF_OBLIGATORY))//yes needed
  	{
      //Make the dropdownlist show an 'empty' option, even though the field is obligatory.
  	  $attr->m_flags ^= AF_OBLIGATORY;
	  $result = $attr->edit($record, $prefix, $mode);
		
	  //Change back to normal behaviour
	  $attr->m_flags |= AF_OBLIGATORY;
	  return $result;
  	}
  	else   //not needed
		return $attr->edit($record, $prefix, $mode);
  }


  function action_linkproject(&$handler)
  {
    $db = &atkGetDb();
    $contractid = $db->escapeSQL($this->m_postvars["contractid"]);
 	$projectid = $db->escapeSQL($this->m_postvars["projectid"]);
    if ($projectid!="" && $contractid != "")
    {
      $db->query("UPDATE project SET contract_id = $contractid WHERE project.id = ".$projectid);
    }
      $this->redirect(session_url("", SESSION_BACK, 2));
  }

  function action_admin(&$handler)
  {
    global $g_sessionManager;
    $this->m_archive = $g_sessionManager->pageVar("archive");

    if ($this->m_archive==1)
    {
      $this->addFilter("contract.status='archived'");
    }
    else
    {
      $this->addFilter("contract.status='active'");
    }
    return $handler->action_admin();
  }

  function action_edit(&$handler)
  {
  	$this->registerLoadScripts();
    return $handler->action_edit();
  }

  function action_add(&$handler)
  {
  	$this->registerLoadScripts();
  	return $handler->action_add();
  }

	/**
   * Register scripts for visibility of period_price
   *
   * Function registers a script that runs on page load.
   * script checks if the period price should be visible or not
   */
  function registerLoadScripts()
  {
  	$page = &$this->getPage();
    $page->register_scriptcode("
      function check_billing_period(srcid, destid, destVarId) {
        var src = document.getElementById(srcid);
    		var dest_ar = document.getElementById(destid);
    		var dest = document.getElementById(destVarId);
    		if(src.options[src.selectedIndex].value == 'no_billing_period')
    		{
	    		dest_ar.style.visibility = 'hidden';
    			dest.value = '';
    		}
    		else
    		{
    			dest_ar.style.visibility = 'visible';
    		}
      }
    ");

    $page->register_loadscript("check_billing_period('billing_period', 'ar_period_price', 'period_price');");
  }

  function adminFooter()
  {
    $res = "" ;
    if ($this->m_archive!=1)
    {
      return atktext("onlyactiverecordsareshown")." ".href(dispatch_url($this->atknodetype(),$this->m_action,array("archive"=>1)),
                                                      atktext('clicktoviewarchive', $this->m_type, $this->m_module))."<br>";
    }
    else
    {
      return atktext("youareinthearchive")." ".href(dispatch_url($this->atknodetype(),$this->m_action,array("archive"=>0)),
                                               atktext('clicktoviewactiverecords', $this->m_type, $this->m_module))."<br>";
    }
    return $res."<br>";
  }

	
  function descriptor_commit()
  {
    return "[description]";
  }

  function descriptor($rec)
  {
    $ret = "";
    if(isset($rec["contractnumber"]) && $rec["contractnumber"]!="") $ret.=$rec["contractnumber"];
    if(isset($rec["contractname"]) && $rec["contractname"]!="")
    {
      if($ret!="") $ret.=" - ";
      $ret.=$rec["contractname"];
    }
    return $ret;
  }

   /**
   * Return rowcolor based on days towards term of notice.
   *
   * @param array record a record
   * @return string output color code or nothing
   */
  function rowColor($record)
  {
    $term_of_notice = sprintf("%d-%02d-%02d", $record["term_of_notice"]["year"], $record["term_of_notice"]["month"], $record["term_of_notice"]["day"]);
    //$days_left = $this->daysLeft(date("Y-m-d"), $term_of_notice);
    $days_left = $this->daysLeft(date("Y-m-d"), $term_of_notice);

    // If contract term of notice is within 15 days, we get red..
    if ($days_left<=15 && $term_of_notice != "0-00-00")
    {
      return COLOR_ERROR;
    }
    // If contract term of notice is within 31 days, we get orange..
    else if ($days_left<=31 && $term_of_notice != "0-00-00")
    {
      return COLOR_WARNING;
    }
    // do nothing (will result in the default color)
  }
    
  /**
   * Return number of days difference between two dates
   *
   * @param string start date (yyyy-mm-dd)
   * @param string end date (yyyy-mm-dd)
   * @return string floored number of days difference.
   */   
  function daysLeft($start, $end)
  {
    if ($start==""||$end=="") return 0;

    $d1 = mktime(12,0,0,substr($start,5,2), substr($start,8,2), substr($start,0,4));
    $d2 = mktime(12,0,0,substr($end,5,2), substr($end,8,2), substr($end,0,4));
    return floor(($d2-$d1)/(60*60*24));
  }

  function initial_values()
  {
    $enddatetime = strtotime("+1 year");
	  return array(
	    "startdate" => array("year"=>(date("Y")),
							"month"=>date("m"),
							"day"=>date("d")),
		"enddate" => array("year"=>(date("Y",$enddatetime)),
							"month"=>date("m",$enddatetime),
							"day"=>date("d",$enddatetime)),
        "status"=>"active",

	);
  }

  //todo: updateDb doesn't update the status for some reason. Query should be changed to using updateDb.
  // but for that the updateDb problem should be found.
  function postUpdate($rec)
  {
  	$expired = false;

  	//Does this contract have an enddate?
  	if($rec['enddate'] != array() && isset($rec['enddate']))
  	{
  	  //get current date as a timestamp
      $now = mktime(12,0,0,date("m"),date("d"),date("Y"));
  
      //get enddate of record as a timestamp.
      $enddate = mktime(12,0,0,$rec['enddate']['month'],$rec['enddate']['day'],$rec['enddate']['year']);
  
      //did it expire?
  	  $expired = ($now > $enddate);
  	}

  	//When status changes to 'archived' All linked projects are set to non-active.
  	//Or if the enddate has passed, all linked projects are set to non-active as well.
  	if(($rec['status'] == 'archived') || $expired)
  	{
  	  $db = &atkGetDb();

      //If contract expired, set its status to archived
      if($expired)
      {
      	//set contract status to archived
      	$query = "UPDATE contract SET contract.status='archived' WHERE contract.id='".$rec['id']."'";
      	$db->query($query);
      }
      
      $contractid = $rec['id'];
      $node = &atkGetNode("project.project");
      
      //Select projects linked to this contract that are active.
      $projects = $node->selectDb("(project.contract_id='$contractid' AND project.status='active')","","","",array("id","name"));
      foreach($projects as $record)
      {
      	$query = "UPDATE project SET project.status='nonactive' WHERE project.id='".$record['id']."'";
      	$db->query($query);
      }
  	}
  	return true;
  }

  function getFormButtons($mode, $record)
  {
    $buttons = array();
    if ($mode == 'edit')
    {
      if($record['status'] == "active")
      {
        $buttons[] = '<input type="submit" class="btn_save" name="deactivate_contract" value="'.$this->text("deactivate_contract").'">';
      }
      else
      {
        $buttons[] = '<input type="submit" class="btn_save" name="activate_contract" value="'.$this->text("activate_contract").'">';
      }
    }
    return array_merge(parent::getFormButtons($mode,$record), $buttons);
  }

  function action_update(&$handler)
  {
    if (isset($this->m_postvars["activate_contract"]) || isset($this->m_postvars["deactivate_contract"]))
    {
      $this->m_postvars["atknoclose"] = 1;
    }
    // call original behaviour
    return $handler->action_update();
  }

  function preUpdate(&$record)
  {
    if (isset($this->m_postvars["activate_contract"]))
    {
      $db = &$this->getDb();
      $db->query("UPDATE project SET status='active' WHERE project.contract_id={$record['id']}");

      $record['status'] = "active";
    }
    elseif (isset($this->m_postvars["deactivate_contract"]))
    {
      $db = &$this->getDb();
      $db->query("UPDATE project SET status='archived' WHERE project.contract_id={$record['id']}");

      $record['status'] = "archived";
    }

    return true;
  }

}

?>